#!/usr/bin/python3
# -*- coding: utf-8 -*-

__VERSION__ = '0.00002'

import os
import sys
import csv
import itertools
import time

from PyQt5 import QtCore
from collections import OrderedDict

from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QAction
from PyQt5.QtWidgets import qApp
from PyQt5.QtWidgets import QTableWidget
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QGridLayout
from PyQt5.QtWidgets import QHBoxLayout
from PyQt5.QtWidgets import QDialog
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QTabWidget
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QFrame
from PyQt5.QtWidgets import QColorDialog
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QCheckBox
from PyQt5.QtWidgets import QScrollArea
from PyQt5.QtWidgets import QTextEdit
from PyQt5.QtWidgets import QLabel
from PyQt5.QtWidgets import QDialogButtonBox
from PyQt5.QtWidgets import QHeaderView
from PyQt5.QtWidgets import QAbstractItemView
from PyQt5.QtWidgets import QTableWidgetItem

from PyQt5.QtGui import QIcon
from PyQt5.QtGui import QColor
from PyQt5.QtGui import QDrag
from PyQt5.QtGui import QTextCursor
from PyQt5.QtGui import QPixmap

from PyQt5.QtCore import Qt
from PyQt5.QtCore import QObject
from PyQt5.QtCore import QMimeData
from PyQt5.QtCore import pyqtSignal

csv.register_dialect('mydialect', delimiter='\t', quoting=csv.QUOTE_MINIMAL)

store = None

import copy

class SettingDialog(QDialog):
    def __init__(self, parent=None):
        super(SettingDialog, self).__init__(parent)
        self.temp_song_d = copy.deepcopy(store.song_g)
        self.grid = QGridLayout()
        self.initUI()
        self.setWindowIcon(QIcon("res/ico/settingPath.ico"))
        self.setWindowTitle("设置")
        self.resize(1920, 1080)

    def initUI(self):
        self.setParent(None)
        c_t = self.grid.takeAt(0)
        while c_t:
            c_t.widget().setParent(None)
            c_t = self.grid.takeAt(0)

        self.grid.addWidget(QLabel("已选歌曲：%d" % len(self.temp_song_d)), 0, 0)
        self.itable = QTableWidget()
        self.itable.setFixedSize(1700, 1000)
        self.itable.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.itable.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.itable.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.itable.setColumnCount(len(store.fieldnames) + 1)
        self.itable.setRowCount(len(self.temp_song_d))
        self.itable.setHorizontalHeaderLabels(store.fieldnames + ['img'])
        self.itable.setSortingEnabled(True)
        for index, (k, song) in enumerate(self.temp_song_d.items()):
            # self.itable.setItem(index + 1, s_index + 1, s_v)
            for s_index, (s_k, s_v) in enumerate(song.items()):
                item = QTableWidgetItem()
                item.setText(str(s_v))
                self.itable.setItem(index, s_index, item)

            item = QWidget()
            label = QLabel(item)
            label.setPixmap(QPixmap(song.get('discimg','')).scaled(85, 85))
            self.itable.setCellWidget(index, len(store.fieldnames), label)
        self.grid.addWidget(self.itable, 1, 1)
        button = QPushButton("删除")
        button.clicked.connect(self.change)
        self.grid.addWidget(button, 0, 2)
        self.grid.addWidget(QLabel("<font color='#ff0000'>选择要删除的歌曲列表，到只剩54首歌</font>"), 2, 0, 1, 3)
        buttonBox = QDialogButtonBox()
        buttonBox.setOrientation(Qt.Horizontal)  # 设置为水平方向
        buttonBox.setStandardButtons(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(self.accept_s)  # 确定
        buttonBox.rejected.connect(self.reject)  # 取消
        self.grid.addWidget(buttonBox, 2, 1)
        self.setLayout(self.grid)

    def change(self):
        for item in self.itable.selectedItems():
            if item.column() == 1:
                self.temp_song_d.pop(item.text())
        self.initUI()
        QApplication.processEvents()

    def accept_s(self):
        store.song_g = copy.deepcopy(self.temp_song_d)
        if len(store.song_g) <= 54:
            self.accept()


class Store(object):
    def __init__(self):
        img_file_list = []
        self.song_g = OrderedDict()
        # self.s_song_d = Ui_Dialog()
        img_path = 'discimg'
        for _, _, t in os.walk(img_path):
            img_file_list = t[:]
        if os.path.exists('Resource/DiscInfo/discstock.csv'):
            with open('Resource/DiscInfo/discstock.csv', 'r', encoding='utf-16') as f:
                self.song_list = []
                for r in csv.DictReader(f, dialect='mydialect'):
                    for img_name in img_file_list:
                        if img_name.startswith(r['name']):
                            r['discimg'] = '%s/%s' % (img_path, img_name)
                    self.song_g[r['name']] = r

        with open('pop_stage.csv', 'r', encoding='utf-8') as f:
            self.song_SP = {}
            f.readline()
            for r in f:
                data = r.split(',')
                self.song_SP[data[1]] = {
                    'stage': data[0],
                    'songname': data[1],
                    'SP_1': data[2],
                    'PT_1': data[3],
                    'Hid_1': data[4],
                    'SP_2': data[5],
                    'PT_2': data[6],
                    'Hid_2': data[7],
                    'SP_3': data[8],
                    'PT_3': data[9],
                    'Hid_3': data[10],
                    'SP_4': data[11],
                    'PT_4': data[12],
                    'Hid_4': data[13]
                }
            print(self.song_SP)
        with open('songlist.csv', 'r', encoding='utf-16') as f:
            self.song_list = []
            for r in csv.DictReader(f, dialect='mydialect'):
                for img_name in img_file_list:
                    if img_name.startswith(r['name']):
                        r['discimg'] = '%s/%s' % (img_path, img_name)
                self.song_list.append(r)

        self.fieldnames = [_ for _ in self.song_list[0].keys() if _ not in ['discimg']]


    def g_song_csv(self):
        import shutil
        try:
            if not os.path.exists('Resource'):
                os.mkdir('Resource')
            if not os.path.exists('Resource/DiscInfo'):
                os.mkdir('Resource/DiscInfo')
        except WindowsError:
            pass
        try:
            temp_songlist = OrderedDict()
            with open('Resource/DiscInfo/discstock.csv', 'w', newline='', encoding='UTF-16') as _:
                writer = csv.DictWriter(_, fieldnames=self.fieldnames, dialect='mydialect')
                writer.writeheader()
                for index, (k, v) in enumerate(self.song_g.items()):
                    v['no'] = index + 1
                    row = {tk: '"%s"' % tv if isinstance(tv, str) and tv.find(',') != -1 else tv for tk, tv in v.items() if
                           tk not in ['discimg']}
                    temp_songlist[row['no']] = row
                    print(row)
                    writer.writerow(row)

            fieldnames_pop = [
                'stage',
                'songname',
                'SP',
                'PT',
                'Hid',
                'SP',
                'PT',
                'Hid',
                'SP',
                'PT',
                'Hid',
                'SP',
                'PT',
                'Hid'
            ]
            for file_i in range(1, 4):
                with open('Resource/DiscInfo/pop_stage_%d.csv' % file_i, 'w', newline='', encoding='UTF-8') as f:
                    f.write('%s\n' % ','.join([fieldnames_pop[0]+str(file_i)]+fieldnames_pop[1:]))
                    for index, (k, v) in enumerate(temp_songlist.items()):
                        f.write('%s\n' % ','.join(map(lambda x: str(x), [
                            v['no'],  # stage1
                            v['name'],  # songname
                            int(store.song_SP[v['name']]['SP_1']) if store.song_SP.get(v['name'], {}).get('SP_1') else 2, # SP
                            1 if int(v['Pop_1']) else 0,  # PT
                            0,  # Hid
                            int(store.song_SP[v['name']]['SP_2']) if store.song_SP.get(v['name'], {}).get('SP_2') else 2, # SP
                            2 if int(v['Pop_2']) else 0,  # PT
                            0,  # Hid
                            int(store.song_SP[v['name']]['SP_3']) if store.song_SP.get(v['name'], {}).get('SP_3') else 2, # SP
                            3 if int(v['Pop_3']) else 0,  # PT
                            0,  # Hid
                            int(store.song_SP[v['name']]['SP_4']) if store.song_SP.get(v['name'], {}).get('SP_4') else 2, # SP
                            4 if int(v['Pop_4']) else 0,  # PT
                            0,  # Hid
                        ])))
                        print(index, k, v)
            print('suc g')
        except:
            import traceback
            traceback.print_exc()


store = Store()


class MovableButton(QPushButton):
    def __init__(self, title, parent, data=None):
        super().__init__(title, parent)
        self.data = data or {}

    def mouseMoveEvent(self, e):

        if e.buttons() != Qt.RightButton:
            return

        mimeData = QMimeData()

        drag = QDrag(self)
        drag.setMimeData(mimeData)
        drag.setHotSpot(e.pos() - self.rect().topLeft())

        dropAction = drag.exec_(Qt.MoveAction)

    def mousePressEvent(self, e):

        super().mousePressEvent(e)

        if e.button() == Qt.LeftButton:
            print(self.data)
            if self.data:
                store.song_g[self.data['name']] = self.data
                if len(store.song_g) >= 54:
                    dialog = SettingDialog()

                    if dialog.exec_():
                        pass

class MyConsole(QWidget):
    def __init__(self, parent):
        QWidget.__init__(self)
        self.parent = parent

        self.initUI()

    # 初始化UI
    def initUI(self):
        self.gridlayout = QGridLayout()

        # # 设置出20 x 20 的格局
        # for i in range(20):
        #     self.gridlayout.setColumnStretch(i, 1)
        #     self.gridlayout.setRowStretch(i, 1)
        #
        # lb1 = QLabel(u'账户：')
        # lb2 = QLabel(u'密码：')
        # self.userEntry = QLineEdit()
        # self.passEntry = QLineEdit()
        # self.passEntry.setEchoMode(QLineEdit.Password)
        # self.loginBtn = QPushButton(u"登录")
        # self.loginBtn.setFixedSize(40, 20)
        # self.loginBtn.clicked.connect(self.onLoginButton)
        #
        # self.gridlayout.addWidget(lb1, 0, 0)
        # self.gridlayout.addWidget(lb2, 1, 0)
        # self.gridlayout.addWidget(self.userEntry, 0, 1, 1, 3)
        # self.gridlayout.addWidget(self.passEntry, 1, 1, 1, 3)
        # self.gridlayout.addWidget(self.loginBtn, 0, 4, 1, 2)

        self.setLayout(self.gridlayout)

        # 响应登录按钮

    def onLoginButton(self):
        username = self.userEntry.text()
        password = self.passEntry.text()
        QMessageBox.about(self, username + u'登录成功', u"密码是：" + password)
        # QTextCodec.setCodecForCStrings(QTextCodec.codecForName("utf-8"))
        print(username + u'登录成功！\n' + u"密码是：" + password)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def init_menubar(self):
        exitAct = QAction(QIcon('exit.png'), '&Exit', self)
        exitAct.setShortcut('Ctrl+Q')
        exitAct.setStatusTip('Exit application')
        exitAct.triggered.connect(qApp.quit)
        self.statusBar()
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(exitAct)

    def init_select(self):
        col = QColor(0, 0, 0)

        self.btn = QPushButton('Dialog', self)
        self.btn.move(10, 30)

        self.btn.clicked.connect(self.showDialog)

        self.frm = QFrame(self)
        self.frm.setStyleSheet("QWidget { background-color: %s }"
                               % col.name())
        self.frm.setGeometry(130, 22, 100, 100)

    def init_checkbox(self):
        cb = QCheckBox('Show title', self)
        cb.move(10, 60)
        cb.toggle()
        cb.stateChanged.connect(self.changeTitle)

    def init_grid(self):
        grid = MyConsole(self)
        grid.setMinimumSize(1850, 9000)
        tab1 = QWidget()
        scroll = QScrollArea()
        scroll.setWidget(grid)
        scroll.setAutoFillBackground(True)
        scroll.setWidgetResizable(True)
        vbox = QVBoxLayout()
        vbox.addWidget(scroll)
        tab1.setLayout(vbox)

        tabs = QTabWidget(self)
        self.tab2 = QTextEdit()

        self.tab3 = QTextEdit()

        tabs.addTab(tab1, u"控制台")
        tabs.addTab(self.tab2, u"日志输出")
        tabs.addTab(self.tab3 , u"说明")

        cursor = self.tab3.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText("""
        POP曲目替换小工具 v {}

        鉴于离线每次想玩不同的歌都要手动修改csv太麻烦，花了一天时间写了个小工具快速换POP歌（3个stage全都一样），
        界面不友好略丑请无视，以后看心情可能会更新
        0. 下载好魔改自制歌曲包解压到根目录，否则因为缺少文件，点了自制歌曲（有封面的）会游戏闪退
        1. 点击想玩的歌曲（重复点击同一首歌无效）
        2. 点击生成按钮，点击后在日志里有提示，会在根目录下生成 .\Resource 文件夹
        3. 把根目录下生成 .\Resource 文件夹复制到DMT3根目录下覆盖
        4. 打开游戏 play your BREAK
        
        程序是用python + QT 写的，QT动态链接库打包出来有点大
        
        2018.12.20
        
        v 0.00002
        更新了查看已选歌曲的功能
        更新了删除已选歌曲的功能
        更新了保存上次记录的功能
        修复了有些歌曲速度是慢一倍不匹配的问题
        """.format(__VERSION__))
        tabs.resize(1920, 960)
        tabs.move(0, 100)

        positions = [(i, j) for i in range(3 * 3 * 18) for j in range(7)]
        for position, song in itertools.zip_longest(positions, store.song_list):
            if not song or song['name'] == '' or not position:
                continue
            # print(song['name'])
            button = MovableButton('{name}: [{nm}] [{hd}] [{mx}] [{ex}]'.format(
                name=song['FullName'],
                nm=song['Pop_1'],
                hd=song['Pop_2'],
                mx=song['Pop_3'],
                ex=song['Pop_4'],
            ), grid, song)
            button.setFixedSize(220, 50)
            button.setToolTip('''
            <b>no: </b> {no}<br />\n
            <b>name: </b> {name}<br />\n
            <b>FullName: </b> {FullName}<br />\n
            <b>Genre: </b> {Genre}<br />\n
            <b>Composer: </b> {Composer}<br />\n
            <b>bg_folder: </b> {bg_folder}<br />\n
            <b>serieslist: </b> {serieslist}<br />\n
            <b>licenselist: </b> {licenselist}<br />\n
            <b>originalbga: </b> {originalbga}<br />\n
            <b>loopBga: </b> {loopBga}<br />\n
            <b>Star_1: </b> {Star_1}<br />\n
            <b>Star_2: </b> {Star_2}<br />\n
            <b>Star_3: </b> {Star_3}<br />\n
            <b>Star_4: </b> {Star_4}<br />\n
            <b>Pop_1: </b> {Pop_1}<br />\n
            <b>Pop_2: </b> {Pop_2}<br />\n
            <b>Pop_3: </b> {Pop_3}<br />\n
            <b>Pop_4: </b> {Pop_4}
            '''.format(
                no=song.get('no'),
                name=song.get('name'),
                FullName=song.get('FullName'),
                Genre=song.get('Genre'),
                Composer=song.get('Composer'),
                bg_folder=song.get('bg_folder'),
                serieslist=song.get('serieslist'),
                licenselist=song.get('licenselist'),
                originalbga=song.get('originalbga'),
                loopBga=song.get('loopBga'),
                Star_1=song.get('Star_1'),
                Star_2=song.get('Star_2'),
                Star_3=song.get('Star_3'),
                Star_4=song.get('Star_4'),
                Pop_1=song.get('Pop_1'),
                Pop_2=song.get('Pop_2'),
                Pop_3=song.get('Pop_3'),
                Pop_4=song.get('Pop_4')
            ))
            w = QWidget()
            hbox = QVBoxLayout(w)

            if song.get('discimg'):
                pixmap = QPixmap(song['discimg'])
                pixmap.scaled(100, 100)
                lbl = QLabel(w)
                lbl.setPixmap(pixmap)
                lbl.setFixedSize(250, 250)
                lbl.setScaledContents(True)
                hbox.addWidget(lbl)

            hbox.addWidget(button)
            w.setLayout(hbox)

            grid.gridlayout.addWidget(w, *position)

            # self.move(300, 150)

    def init_move(self):
        self.setAcceptDrops(True)
        self.button = QPushButton("生成", self)
        self.button.setFixedSize(200, 80)
        # self.button.setText('生成列表 已选:%d' % len(store.song_g))
        self.button.clicked.connect(store.g_song_csv)
        self.button.move(10, 10)

        textL = QLabel()
        textL.setText('已选:%d' % len(store.song_g))
        textL.setFixedSize(200, 80)
        textL.move(210, 10)

        def get_list():
            dialog = SettingDialog()
            if dialog.exec_():
                pass
        button = QPushButton("已选列表", self)
        button.setFixedSize(200, 80)
        button.clicked.connect(get_list)
        button.move(410, 10)

    def showDialog(self):

        col = QColorDialog.getColor()

        if col.isValid():
            self.frm.setStyleSheet("QWidget { background-color: %s }"
                                   % col.name())

    def changeTitle(self, state):

        if state == Qt.Checked:
            self.setWindowTitle('QCheckBox')
        else:
            self.setWindowTitle(' ')

    def dragEnterEvent(self, e):
        e.accept()
        e.dropAction()
        print(dir(e))
        for i in dir(e):
            try:
                print(i, ':', getattr(e, i))
            except:
                pass

    def dropEvent(self, e):
        position = e.pos()
        self.button.move(position)
        e.setDropAction(Qt.MoveAction)
        e.accept()

    def initUI(self):
        # self.init_menubar()
        # self.init_select()
        # self.init_checkbox()
        self.init_move()
        self.init_grid()

        self.setGeometry(50, 50, 1920, 1080)
        self.setWindowTitle('Technika换POP歌曲小工具 v {} By DJMIN'.format(__VERSION__))
        self.show()

        # 重定向输出
        sys.stdout = EmittingStream(textWritten=self.normalOutputWritten)
        sys.stderr = EmittingStream(textWritten=self.normalOutputWritten)

    def __del__(self):
        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__

    def normalOutputWritten(self, text):
        cursor = self.tab2.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText(text)
        self.tab2.setTextCursor(cursor)
        self.tab2.ensureCursorVisible()


class EmittingStream(QObject):
    textWritten = pyqtSignal(str)

    def write(self, text):
        self.textWritten.emit(str(text))


def main():
    app = QApplication(sys.argv)
    win = MainWindow()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
